{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 查看FashionMNIST原始数据格式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:32.363026Z",
     "start_time": "2025-06-26T01:43:29.447990Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(<PIL.Image.Image image mode=L size=28x28 at 0x17ECFD2D010>, 9)\n"
     ]
    },
    {
     "data": {
      "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/wAALCAAcABwBAREA/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/9oACAEBAAA/APn+tbw1oNx4m8QWmkWx2yXD4LkZCADJJ+gFbviL4a63oc7COE3MW4hdn38duD976jNc9daDqllIsc9lKrMu4YGeMkdR7gj8KzcV7H8BtEvV16+1iWCeG1Wz8mOV02pIzupwCeuAp6Z98cZ90aIzLIlw0c0ZJ4KgjHoeOa+evjS9n/wnMcNxBPCYLKONFhA2FNzMpGenDcgd816V4K03wefC+m3NlpVhP+5QSXBiR5fMx825iMg5zwce3FdbOzTwgW90lu6uCm8eYrL02soIyCPQgggEdMGQ3cluiPNK0rJwrRQBNueuMkt+teNfGKxsdY8WWdxNqcNo66eieXMwVsb5DnH415Hp2rajpE5n02/urOUjBe3laMkehIPIrVm8eeLrhNknibVivoLtx/I1UPinxC3XXtUP1vJP8ay5JZJpGkldnduSzHJP41//2Q==",
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAAAAABXZoBIAAACS0lEQVR4AWKgA2BkYOD1ZGBgZAHZxcjIAKZBbBBm+quS8v3rj1N/GBiZGP8wMKNIMv91cnnCzuU65+X/vww8/76hSP5iMFVgZtpp2HXm8nUz02PHGUHGQTHjf9cugd//GE7f+cUo8ft0yDSEJCMDw/8TCgyMf34x/Ph3/vYfT0VphLH/GRgY3kt+Z2fl+cH5z8aSSWwHqmsZuJiZvn18p/CPkYnr7z9ZBiaofQwMjMwMPFI/frH++sr/j537K9sldhOE5H9mhnBJJg4Gbtlf7L//cQhvusaCkGT5xXDlBxsXl6rSD2Yunr9PoraeYAGZx8T4+x/DHwaGbV+/s/1/zczxm+H3P2a9jwxMDMz///z6+Y+BwW7ime9v//z78/XrXw6GbwxsX4NAYc3AICSlJhmk/oPpN+czVjbhX1zHeOz+fWR9qcnIYNkkKvCX+cMfrl+M36+HneEVVGC4x/v5GycPHxcj83GpP3+/MTB/Z2DgF0lwy3z24/49VeFfrLxsf+UBY0xqv8vDw87Ayv/4mSiTRACHIrexMdMvJjYGRlYLlpeP+X485mHje/eQ5/uPP+svKwj9+vD77y/Wf4xsaixP/z/mFvnw5jULOysHL9Mbza+P37O/+f3nN6fERwOWC+sTn937wcPGwcb88+//by/+/WX5wfPrw4fffxRfMjIweBWLv/7wl5mNhZnxPysrGysjA+NLBrZ/EpfCGJn+MTA4tYnxMzGz/GV8+f/pvy/MDP9/f2Paff0YJBAYGBg0RN/LPPx1Fx5HFDIAaCTYdiCc4RIAAAAASUVORK5CYII=",
      "text/plain": [
       "<PIL.Image.Image image mode=L size=28x28>"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "import torchvision\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from torchvision import datasets, transforms\n",
    "from deeplearning_func import EarlyStopping, ModelSaver,train_classification_model,plot_learning_curves\n",
    "from deeplearning_func import evaluate_classification_model as evaluate_model\n",
    "# 加载Fashion MNIST数据集，张量就是和numpy数组一样\n",
    "transform = transforms.Compose([])\n",
    "train_dataset = datasets.FashionMNIST(root='./data', train=True, download=True, transform=transform)\n",
    "test_dataset = datasets.FashionMNIST(root='./data', train=False, download=True, transform=transform)\n",
    "print(train_dataset[0])\n",
    "train_dataset[0][0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 加载数据并处理为tensor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:32.407799Z",
     "start_time": "2025-06-26T01:43:32.363026Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练集形状: (60000, 28, 28)\n",
      "训练集标签数量: 60000\n",
      "测试集形状: (10000, 28, 28)\n",
      "测试集标签数量: 10000\n"
     ]
    }
   ],
   "source": [
    "# 加载Fashion MNIST数据集，张量就是和numpy数组一样\n",
    "transform = transforms.Compose([\n",
    "    transforms.ToTensor(),\n",
    "    transforms.Normalize((0.286,), (0.353,))  \n",
    "])\n",
    "train_dataset = datasets.FashionMNIST(root='./data', train=True, download=True, transform=transform)\n",
    "test_dataset = datasets.FashionMNIST(root='./data', train=False, download=True, transform=transform)\n",
    "\n",
    "# 获取图像和标签\n",
    "# 注意：由于使用了transform，图像已经被转换为张量且标准化\n",
    "# 我们需要从dataset中提取原始图像用于显示\n",
    "train_images = train_dataset.data.numpy()\n",
    "train_labels = train_dataset.targets.numpy()\n",
    "test_images = test_dataset.data.numpy()\n",
    "test_labels = test_dataset.targets.numpy()\n",
    "\n",
    "# 定义类别名称\n",
    "class_names = ['T-shirt/top', '裤子', '套头衫', '连衣裙', '外套',\n",
    "               '凉鞋', '衬衫', '运动鞋', '包', '短靴']\n",
    "\n",
    "# 查看数据集基本信息\n",
    "print(f\"训练集形状: {train_images.shape}\")\n",
    "print(f\"训练集标签数量: {len(train_labels)}\")\n",
    "print(f\"测试集形状: {test_images.shape}\")\n",
    "print(f\"测试集标签数量: {len(test_labels)}\")\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 把数据集划分为训练集55000和验证集5000，并给DataLoader"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:33.144223Z",
     "start_time": "2025-06-26T01:43:33.135368Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练集大小: 55000\n",
      "验证集大小: 5000\n",
      "测试集大小: 10000\n",
      "批次大小: 64\n",
      "训练批次数: 860\n"
     ]
    }
   ],
   "source": [
    "# 从训练集中划分出验证集\n",
    "train_size = 55000\n",
    "val_size = 5000\n",
    "# 设置随机种子以确保每次得到相同的随机划分结果\n",
    "generator = torch.Generator().manual_seed(42)\n",
    "train_subset, val_subset = torch.utils.data.random_split(\n",
    "    train_dataset, \n",
    "    [train_size, val_size],\n",
    "    generator=generator #设置随机种子，确保每次得到相同的随机划分结果\n",
    ")\n",
    "\n",
    "# 创建数据加载器\n",
    "batch_size = 64\n",
    "train_loader = torch.utils.data.DataLoader(\n",
    "    train_subset,\n",
    "    batch_size=batch_size,\n",
    "    shuffle=True #打乱数据集，每次迭代时，数据集的顺序都会被打乱\n",
    ")\n",
    "\n",
    "val_loader = torch.utils.data.DataLoader(\n",
    "    val_subset,\n",
    "    batch_size=batch_size,\n",
    "    shuffle=False\n",
    ")\n",
    "\n",
    "test_loader = torch.utils.data.DataLoader(\n",
    "    test_dataset,\n",
    "    batch_size=batch_size,\n",
    "    shuffle=False\n",
    ")\n",
    "\n",
    "# 打印数据集大小信息\n",
    "print(f\"训练集大小: {len(train_subset)}\")\n",
    "print(f\"验证集大小: {len(val_subset)}\")\n",
    "print(f\"测试集大小: {len(test_dataset)}\")\n",
    "print(f\"批次大小: {batch_size}\")\n",
    "print(f\"训练批次数: {len(train_loader)}\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:33.148120Z",
     "start_time": "2025-06-26T01:43:33.145230Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "55040"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "64*860"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 搭建模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([20, 100])\n"
     ]
    }
   ],
   "source": [
    "#理解每个接口的方法，单独写例子\n",
    "import torch.nn as nn\n",
    "m=nn.BatchNorm1d(100)\n",
    "x=torch.randn(20,100)\n",
    "print(m(x).shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:33.152657Z",
     "start_time": "2025-06-26T01:43:33.148120Z"
    }
   },
   "outputs": [],
   "source": [
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "class NeuralNetwork(nn.Module):\n",
    "    def __init__(self, layers_num=2):\n",
    "        super().__init__()\n",
    "        self.flatten = nn.Flatten()\n",
    "        # 多加几层\n",
    "        self.linear_selu_stack = nn.Sequential(\n",
    "            nn.Linear(28 * 28, 100),\n",
    "            nn.SELU(),\n",
    "            nn.AlphaDropout(p=0.2)\n",
    "        )\n",
    "        # 加19层\n",
    "        for i in range(1, layers_num):\n",
    "            self.linear_selu_stack.add_module(f\"Linear_{i}\", nn.Linear(100, 100))\n",
    "            self.linear_selu_stack.add_module(f\"selu\", nn.SELU())\n",
    "        # 输出层\n",
    "        self.linear_selu_stack.add_module(\"Output Layer\", nn.Linear(100, 10))\n",
    "        \n",
    "        # 初始化权重\n",
    "        self.init_weights()\n",
    "        \n",
    "    def init_weights(self):\n",
    "        \"\"\"使用 xavier 均匀分布来初始化全连接层的权重 W\"\"\"\n",
    "        # print('''初始化权重''')\n",
    "        for m in self.modules():\n",
    "            # print(m)\n",
    "            # print('-'*50)\n",
    "            if isinstance(m, nn.Linear):#判断m是否为全连接层\n",
    "                # https://pytorch.org/docs/stable/nn.init.html\n",
    "                nn.init.xavier_uniform_(m.weight) # xavier 均匀分布初始化权重\n",
    "                nn.init.zeros_(m.bias) # 全零初始化偏置项\n",
    "        # print('''初始化权重完成''')\n",
    "    def forward(self, x):\n",
    "        # x.shape [batch size, 1, 28, 28]\n",
    "        x = self.flatten(x)  \n",
    "        # 展平后 x.shape [batch size, 28 * 28]\n",
    "        logits = self.linear_selu_stack(x)\n",
    "        # logits.shape [batch size, 10]\n",
    "        return logits\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:33.185031Z",
     "start_time": "2025-06-26T01:43:33.152657Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "批次图像形状: torch.Size([64, 1, 28, 28])\n",
      "批次标签形状: torch.Size([64])\n",
      "----------------------------------------------------------------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "# 实例化模型\n",
    "model = NeuralNetwork(layers_num=19)\n",
    "\n",
    "# 从train_loader获取第一个批次的数据\n",
    "dataiter = iter(train_loader)\n",
    "images, labels = next(dataiter)\n",
    "\n",
    "# 查看批次数据的形状\n",
    "print(\"批次图像形状:\", images.shape)\n",
    "print(\"批次标签形状:\", labels.shape)\n",
    "\n",
    "\n",
    "print('-'*100)\n",
    "# 进行前向传播\n",
    "with torch.no_grad():  # 不需要计算梯度\n",
    "    outputs = model(images)\n",
    "    \n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:33.203053Z",
     "start_time": "2025-06-26T01:43:33.199532Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "需要求梯度的参数总量: 261310\n",
      "----------------------------------------------------------------------------------------------------\n",
      "模型总参数量: 261310\n",
      "\n",
      "各层参数量明细:\n",
      "linear_selu_stack.0.weight: 78400 参数\n",
      "linear_selu_stack.0.bias: 100 参数\n",
      "linear_selu_stack.Linear_1.weight: 10000 参数\n",
      "linear_selu_stack.Linear_1.bias: 100 参数\n",
      "linear_selu_stack.Linear_2.weight: 10000 参数\n",
      "linear_selu_stack.Linear_2.bias: 100 参数\n",
      "linear_selu_stack.Linear_3.weight: 10000 参数\n",
      "linear_selu_stack.Linear_3.bias: 100 参数\n",
      "linear_selu_stack.Linear_4.weight: 10000 参数\n",
      "linear_selu_stack.Linear_4.bias: 100 参数\n",
      "linear_selu_stack.Linear_5.weight: 10000 参数\n",
      "linear_selu_stack.Linear_5.bias: 100 参数\n",
      "linear_selu_stack.Linear_6.weight: 10000 参数\n",
      "linear_selu_stack.Linear_6.bias: 100 参数\n",
      "linear_selu_stack.Linear_7.weight: 10000 参数\n",
      "linear_selu_stack.Linear_7.bias: 100 参数\n",
      "linear_selu_stack.Linear_8.weight: 10000 参数\n",
      "linear_selu_stack.Linear_8.bias: 100 参数\n",
      "linear_selu_stack.Linear_9.weight: 10000 参数\n",
      "linear_selu_stack.Linear_9.bias: 100 参数\n",
      "linear_selu_stack.Linear_10.weight: 10000 参数\n",
      "linear_selu_stack.Linear_10.bias: 100 参数\n",
      "linear_selu_stack.Linear_11.weight: 10000 参数\n",
      "linear_selu_stack.Linear_11.bias: 100 参数\n",
      "linear_selu_stack.Linear_12.weight: 10000 参数\n",
      "linear_selu_stack.Linear_12.bias: 100 参数\n",
      "linear_selu_stack.Linear_13.weight: 10000 参数\n",
      "linear_selu_stack.Linear_13.bias: 100 参数\n",
      "linear_selu_stack.Linear_14.weight: 10000 参数\n",
      "linear_selu_stack.Linear_14.bias: 100 参数\n",
      "linear_selu_stack.Linear_15.weight: 10000 参数\n",
      "linear_selu_stack.Linear_15.bias: 100 参数\n",
      "linear_selu_stack.Linear_16.weight: 10000 参数\n",
      "linear_selu_stack.Linear_16.bias: 100 参数\n",
      "linear_selu_stack.Linear_17.weight: 10000 参数\n",
      "linear_selu_stack.Linear_17.bias: 100 参数\n",
      "linear_selu_stack.Linear_18.weight: 10000 参数\n",
      "linear_selu_stack.Linear_18.bias: 100 参数\n",
      "linear_selu_stack.Output Layer.weight: 1000 参数\n",
      "linear_selu_stack.Output Layer.bias: 10 参数\n"
     ]
    }
   ],
   "source": [
    "# 统计需要求梯度的参数总量\n",
    "trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)\n",
    "print(f\"需要求梯度的参数总量: {trainable_params}\")\n",
    "\n",
    "print('-'*100)\n",
    "\n",
    "# 计算模型的总参数量\n",
    "total_params = sum(p.numel() for p in model.parameters())\n",
    "print(f\"模型总参数量: {total_params}\")\n",
    "\n",
    "# 查看每层参数量明细\n",
    "print(\"\\n各层参数量明细:\")\n",
    "for name, param in model.named_parameters():\n",
    "    print(f\"{name}: {param.numel()} 参数\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:33.217395Z",
     "start_time": "2025-06-26T01:43:33.203561Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "OrderedDict([('linear_selu_stack.0.weight',\n",
       "              tensor([[-0.0564, -0.0303, -0.0469,  ...,  0.0619,  0.0574, -0.0615],\n",
       "                      [-0.0218,  0.0667,  0.0257,  ...,  0.0378, -0.0170,  0.0510],\n",
       "                      [-0.0341, -0.0559, -0.0354,  ...,  0.0404,  0.0271,  0.0388],\n",
       "                      ...,\n",
       "                      [ 0.0790, -0.0027, -0.0349,  ...,  0.0186,  0.0003, -0.0122],\n",
       "                      [-0.0715,  0.0708,  0.0188,  ...,  0.0223,  0.0751,  0.0346],\n",
       "                      [ 0.0357, -0.0112,  0.0415,  ...,  0.0198,  0.0478,  0.0141]])),\n",
       "             ('linear_selu_stack.0.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_1.weight',\n",
       "              tensor([[-0.1196,  0.0684, -0.1501,  ..., -0.1451, -0.0875,  0.0143],\n",
       "                      [ 0.0610, -0.1690,  0.1165,  ...,  0.0201, -0.0012, -0.0656],\n",
       "                      [ 0.0654, -0.1285,  0.0543,  ..., -0.0788, -0.0177,  0.0356],\n",
       "                      ...,\n",
       "                      [-0.0790,  0.0339,  0.0658,  ..., -0.0622, -0.1684,  0.0823],\n",
       "                      [ 0.0492, -0.0634,  0.0629,  ...,  0.0988, -0.0132, -0.0618],\n",
       "                      [-0.1276, -0.0612, -0.1155,  ...,  0.1442, -0.1596,  0.0838]])),\n",
       "             ('linear_selu_stack.Linear_1.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_2.weight',\n",
       "              tensor([[-0.0286, -0.0776, -0.0052,  ...,  0.0319,  0.0557,  0.1532],\n",
       "                      [-0.0204,  0.0755,  0.0811,  ..., -0.0896, -0.0808, -0.0392],\n",
       "                      [-0.1358, -0.0279,  0.0123,  ..., -0.0930, -0.1387, -0.0459],\n",
       "                      ...,\n",
       "                      [-0.0879, -0.1661, -0.0046,  ...,  0.0390, -0.0221,  0.0055],\n",
       "                      [ 0.1655,  0.1639,  0.1311,  ...,  0.1009,  0.1602, -0.0476],\n",
       "                      [-0.0494,  0.1068,  0.0054,  ..., -0.1551,  0.1224, -0.0698]])),\n",
       "             ('linear_selu_stack.Linear_2.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_3.weight',\n",
       "              tensor([[-0.0567, -0.0425,  0.0496,  ..., -0.1643, -0.1660,  0.0565],\n",
       "                      [-0.1490,  0.1197,  0.0832,  ...,  0.1079,  0.0287, -0.0263],\n",
       "                      [ 0.0499,  0.0266, -0.0114,  ..., -0.0584, -0.1158,  0.1185],\n",
       "                      ...,\n",
       "                      [-0.1655, -0.1105, -0.1023,  ...,  0.1426,  0.1716, -0.0410],\n",
       "                      [ 0.0548,  0.1695,  0.1171,  ..., -0.0372, -0.0805,  0.0261],\n",
       "                      [-0.1275,  0.0660,  0.0015,  ...,  0.0686,  0.1469,  0.1542]])),\n",
       "             ('linear_selu_stack.Linear_3.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_4.weight',\n",
       "              tensor([[-0.1312, -0.1732,  0.0554,  ..., -0.1111, -0.1358,  0.0304],\n",
       "                      [ 0.1276, -0.0176, -0.1051,  ..., -0.0064, -0.0202, -0.1071],\n",
       "                      [-0.0653, -0.1113,  0.0209,  ..., -0.0631,  0.1280, -0.0714],\n",
       "                      ...,\n",
       "                      [-0.1072, -0.1430,  0.0732,  ..., -0.0530, -0.0775,  0.0890],\n",
       "                      [-0.1308, -0.0973, -0.1562,  ...,  0.0630, -0.0955,  0.1287],\n",
       "                      [ 0.1114,  0.0051, -0.0405,  ...,  0.0012,  0.1660,  0.0383]])),\n",
       "             ('linear_selu_stack.Linear_4.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_5.weight',\n",
       "              tensor([[ 0.1704,  0.1209, -0.0901,  ...,  0.1001, -0.0493, -0.1658],\n",
       "                      [-0.0158, -0.1523, -0.0991,  ...,  0.0616,  0.0823, -0.1089],\n",
       "                      [-0.0113,  0.1248, -0.1294,  ...,  0.0321,  0.1025,  0.0267],\n",
       "                      ...,\n",
       "                      [-0.1492,  0.1512, -0.0245,  ...,  0.1534,  0.0835, -0.1227],\n",
       "                      [ 0.0885,  0.0570,  0.1394,  ...,  0.0968,  0.0989, -0.1075],\n",
       "                      [ 0.0222,  0.0092, -0.0203,  ...,  0.0148,  0.1631,  0.0992]])),\n",
       "             ('linear_selu_stack.Linear_5.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_6.weight',\n",
       "              tensor([[-0.0637, -0.0258, -0.1473,  ...,  0.0720,  0.1555, -0.1357],\n",
       "                      [-0.1355, -0.0220,  0.1420,  ..., -0.0458,  0.1370, -0.1124],\n",
       "                      [ 0.0718, -0.1541, -0.0208,  ...,  0.0303, -0.1715, -0.0105],\n",
       "                      ...,\n",
       "                      [-0.0609, -0.0814, -0.0275,  ..., -0.1284,  0.0314,  0.0131],\n",
       "                      [ 0.1567, -0.1416,  0.1520,  ...,  0.1035,  0.0349, -0.1310],\n",
       "                      [ 0.0164,  0.0271,  0.1332,  ...,  0.1699,  0.0221,  0.1408]])),\n",
       "             ('linear_selu_stack.Linear_6.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_7.weight',\n",
       "              tensor([[ 0.1231, -0.0502,  0.0434,  ..., -0.0660,  0.0752,  0.1570],\n",
       "                      [ 0.0811,  0.1378,  0.1210,  ...,  0.0498,  0.1275,  0.0278],\n",
       "                      [ 0.1201, -0.0347, -0.0516,  ..., -0.0052, -0.0144,  0.0772],\n",
       "                      ...,\n",
       "                      [ 0.1148, -0.1605, -0.0554,  ...,  0.0985,  0.0841,  0.1652],\n",
       "                      [-0.0117, -0.1544, -0.1489,  ..., -0.0854,  0.0362,  0.1031],\n",
       "                      [-0.0785,  0.1479,  0.0982,  ..., -0.1486, -0.0387,  0.0557]])),\n",
       "             ('linear_selu_stack.Linear_7.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_8.weight',\n",
       "              tensor([[ 0.0204, -0.1515,  0.0395,  ..., -0.0652, -0.1170, -0.0045],\n",
       "                      [ 0.0725, -0.1014, -0.1039,  ..., -0.0474, -0.1554,  0.1339],\n",
       "                      [-0.0330,  0.0667,  0.1607,  ..., -0.0237,  0.1075, -0.1130],\n",
       "                      ...,\n",
       "                      [ 0.1069,  0.0477,  0.0975,  ..., -0.1236,  0.0941, -0.1701],\n",
       "                      [ 0.0903, -0.0108,  0.0458,  ...,  0.0856,  0.1422,  0.1331],\n",
       "                      [-0.0114,  0.0905, -0.1682,  ...,  0.1218,  0.1447,  0.0826]])),\n",
       "             ('linear_selu_stack.Linear_8.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_9.weight',\n",
       "              tensor([[-0.1223, -0.1551, -0.0811,  ...,  0.1128, -0.1470,  0.1673],\n",
       "                      [-0.0114, -0.0275,  0.0508,  ..., -0.1016,  0.0636, -0.0333],\n",
       "                      [ 0.0888, -0.1448, -0.0108,  ...,  0.0910, -0.0519, -0.1671],\n",
       "                      ...,\n",
       "                      [ 0.0489,  0.0742,  0.0924,  ..., -0.0322, -0.0578, -0.0104],\n",
       "                      [-0.0220, -0.0393, -0.0881,  ..., -0.0612, -0.0595,  0.1395],\n",
       "                      [-0.0097,  0.0648, -0.1500,  ..., -0.0658, -0.1279, -0.0223]])),\n",
       "             ('linear_selu_stack.Linear_9.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_10.weight',\n",
       "              tensor([[ 0.1593,  0.1448, -0.0881,  ..., -0.0661, -0.0247,  0.1086],\n",
       "                      [-0.0099, -0.1334,  0.0967,  ..., -0.0834,  0.1192,  0.1631],\n",
       "                      [ 0.1067, -0.0964, -0.0025,  ...,  0.0941,  0.0535,  0.1332],\n",
       "                      ...,\n",
       "                      [ 0.1442,  0.1225, -0.0862,  ..., -0.1314,  0.1668, -0.1024],\n",
       "                      [ 0.0392,  0.0904,  0.0480,  ..., -0.1230, -0.0921, -0.0881],\n",
       "                      [ 0.0522, -0.0723, -0.0244,  ..., -0.0373,  0.0416,  0.1185]])),\n",
       "             ('linear_selu_stack.Linear_10.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_11.weight',\n",
       "              tensor([[-0.1637,  0.0196,  0.0824,  ...,  0.0630,  0.0439, -0.0347],\n",
       "                      [-0.1215, -0.0801, -0.1306,  ...,  0.1560,  0.0640,  0.0127],\n",
       "                      [ 0.0181,  0.0885,  0.0868,  ...,  0.0159, -0.0402, -0.1130],\n",
       "                      ...,\n",
       "                      [-0.0813, -0.1730, -0.0829,  ...,  0.1731, -0.0606, -0.0698],\n",
       "                      [ 0.0219, -0.0966, -0.0173,  ..., -0.0073, -0.1252, -0.0035],\n",
       "                      [-0.1173, -0.0095, -0.1367,  ..., -0.1361,  0.0721,  0.1156]])),\n",
       "             ('linear_selu_stack.Linear_11.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_12.weight',\n",
       "              tensor([[ 2.2874e-02,  1.5246e-01, -1.7037e-01,  ...,  1.1914e-01,\n",
       "                        1.1225e-01,  1.2899e-01],\n",
       "                      [ 1.1257e-01,  1.6648e-01, -3.4853e-02,  ...,  1.5480e-01,\n",
       "                        1.4608e-01,  1.6442e-01],\n",
       "                      [-1.1194e-01, -2.3201e-05,  5.3010e-02,  ...,  4.1358e-02,\n",
       "                        1.4292e-01,  1.2215e-01],\n",
       "                      ...,\n",
       "                      [ 6.9198e-02, -1.3421e-01,  1.2797e-02,  ..., -8.7528e-02,\n",
       "                        1.2397e-01, -3.1803e-02],\n",
       "                      [-3.2317e-02,  5.3549e-02, -1.5300e-01,  ...,  1.5562e-01,\n",
       "                       -6.7507e-02, -1.2787e-01],\n",
       "                      [-3.0366e-02, -9.5521e-02, -1.4174e-01,  ...,  1.0161e-01,\n",
       "                        9.4371e-02, -8.6975e-02]])),\n",
       "             ('linear_selu_stack.Linear_12.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_13.weight',\n",
       "              tensor([[ 0.0925,  0.1621,  0.0622,  ..., -0.1286, -0.0271, -0.1603],\n",
       "                      [ 0.1229, -0.1493, -0.1031,  ..., -0.0780, -0.0038, -0.0608],\n",
       "                      [ 0.1223,  0.0740,  0.0067,  ...,  0.0650, -0.0105,  0.1263],\n",
       "                      ...,\n",
       "                      [ 0.0697,  0.0178,  0.1009,  ..., -0.1089,  0.1314, -0.1326],\n",
       "                      [ 0.1403,  0.1302, -0.0695,  ...,  0.1566,  0.0695, -0.0116],\n",
       "                      [-0.1321,  0.1070,  0.0975,  ...,  0.0848, -0.1299, -0.0084]])),\n",
       "             ('linear_selu_stack.Linear_13.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_14.weight',\n",
       "              tensor([[-0.1373, -0.0172, -0.0830,  ..., -0.1464, -0.1260, -0.1534],\n",
       "                      [-0.0707, -0.1250,  0.0471,  ..., -0.1716,  0.0647,  0.0744],\n",
       "                      [-0.1196,  0.0097, -0.0790,  ...,  0.0573,  0.0352,  0.0962],\n",
       "                      ...,\n",
       "                      [-0.0179, -0.0305,  0.1554,  ..., -0.0572,  0.0510, -0.0745],\n",
       "                      [-0.0639,  0.0464,  0.0116,  ..., -0.1441, -0.0427,  0.1352],\n",
       "                      [-0.1238,  0.0740, -0.1397,  ...,  0.1643,  0.1481,  0.0684]])),\n",
       "             ('linear_selu_stack.Linear_14.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_15.weight',\n",
       "              tensor([[-0.1588, -0.0312, -0.1073,  ..., -0.0944,  0.0891,  0.0398],\n",
       "                      [-0.1534, -0.0176,  0.0379,  ..., -0.0292, -0.1187, -0.0233],\n",
       "                      [ 0.0989, -0.0390, -0.0127,  ...,  0.1033, -0.0417, -0.1341],\n",
       "                      ...,\n",
       "                      [-0.0219,  0.0859, -0.1502,  ..., -0.1343,  0.0117, -0.0546],\n",
       "                      [-0.1339, -0.1588,  0.0236,  ...,  0.0978, -0.1069, -0.0373],\n",
       "                      [ 0.1729,  0.0290,  0.0917,  ...,  0.1218,  0.1010,  0.1457]])),\n",
       "             ('linear_selu_stack.Linear_15.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_16.weight',\n",
       "              tensor([[-0.0661, -0.1459, -0.1463,  ...,  0.0664,  0.0599,  0.0217],\n",
       "                      [ 0.1162, -0.1075, -0.0549,  ..., -0.1272,  0.1452, -0.0026],\n",
       "                      [-0.0538, -0.1036, -0.1419,  ...,  0.0267, -0.0667,  0.0897],\n",
       "                      ...,\n",
       "                      [ 0.0787, -0.0109, -0.0210,  ..., -0.0711, -0.1226,  0.1388],\n",
       "                      [ 0.1189, -0.0608, -0.1058,  ..., -0.0707,  0.0513, -0.1232],\n",
       "                      [ 0.0263, -0.0781,  0.0607,  ...,  0.0600, -0.0504, -0.0139]])),\n",
       "             ('linear_selu_stack.Linear_16.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_17.weight',\n",
       "              tensor([[-0.1038,  0.0399, -0.0809,  ..., -0.1060, -0.1114,  0.0174],\n",
       "                      [-0.0505,  0.1486, -0.0722,  ...,  0.0156, -0.0510,  0.0615],\n",
       "                      [-0.1326, -0.0318, -0.0762,  ...,  0.1134,  0.1041,  0.0098],\n",
       "                      ...,\n",
       "                      [-0.1072,  0.1073, -0.0961,  ..., -0.0947, -0.0760, -0.1019],\n",
       "                      [ 0.1156, -0.1570,  0.0043,  ...,  0.0356, -0.0966, -0.1302],\n",
       "                      [ 0.0296,  0.0123, -0.1416,  ...,  0.1268,  0.1100,  0.1472]])),\n",
       "             ('linear_selu_stack.Linear_17.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Linear_18.weight',\n",
       "              tensor([[-0.0325, -0.0149, -0.0954,  ..., -0.0096, -0.0590,  0.1398],\n",
       "                      [ 0.0764,  0.1644,  0.1110,  ..., -0.1564,  0.0502,  0.1688],\n",
       "                      [-0.1598,  0.1612,  0.1396,  ...,  0.0089,  0.0774,  0.1436],\n",
       "                      ...,\n",
       "                      [-0.1391,  0.1112,  0.0576,  ...,  0.1202, -0.0047, -0.1509],\n",
       "                      [-0.1489, -0.1646, -0.0037,  ..., -0.1348, -0.0627,  0.0102],\n",
       "                      [ 0.0145, -0.0617,  0.0909,  ...,  0.1564,  0.0808, -0.0742]])),\n",
       "             ('linear_selu_stack.Linear_18.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
       "                      0., 0., 0., 0.])),\n",
       "             ('linear_selu_stack.Output Layer.weight',\n",
       "              tensor([[-0.0637,  0.0405, -0.2252,  0.0726, -0.0745,  0.2240,  0.1247, -0.0743,\n",
       "                        0.1724,  0.1752, -0.0172,  0.2072, -0.1466, -0.2058,  0.0578,  0.1689,\n",
       "                       -0.0187, -0.2307, -0.0375, -0.1695,  0.0997,  0.2273,  0.1601, -0.0680,\n",
       "                       -0.2174,  0.0460,  0.0589,  0.1632,  0.2180, -0.0080, -0.1637,  0.1383,\n",
       "                        0.1660, -0.1887, -0.1333, -0.0002,  0.1750, -0.0253, -0.2259,  0.0263,\n",
       "                       -0.0284, -0.1884, -0.1033, -0.0173,  0.1706,  0.1793, -0.0849, -0.2086,\n",
       "                        0.1005,  0.1458, -0.1302, -0.0782, -0.1859,  0.2177,  0.2279,  0.0290,\n",
       "                        0.2047,  0.0179,  0.1583, -0.0665, -0.1657, -0.0145,  0.1976, -0.2135,\n",
       "                        0.1585, -0.1829,  0.2089, -0.1630,  0.1899, -0.1352, -0.1503, -0.1858,\n",
       "                       -0.1848, -0.0308, -0.1623,  0.1324, -0.0615,  0.1762, -0.2296,  0.0124,\n",
       "                       -0.1863, -0.1663, -0.2323,  0.0580,  0.1291, -0.1049,  0.0748, -0.1878,\n",
       "                       -0.1780, -0.0091,  0.1254, -0.1233,  0.0891,  0.1138,  0.0409,  0.1666,\n",
       "                        0.2225,  0.0860,  0.1195, -0.0968],\n",
       "                      [ 0.0191, -0.1375,  0.0176, -0.0142, -0.0313,  0.0932,  0.0274,  0.0886,\n",
       "                        0.1949, -0.0811, -0.0030, -0.0617,  0.0190,  0.2050, -0.2103,  0.0910,\n",
       "                        0.0660,  0.0669, -0.1608, -0.1194,  0.1449, -0.0865,  0.0463, -0.0882,\n",
       "                       -0.0472,  0.1457,  0.0661, -0.0385, -0.0211, -0.0401, -0.1795,  0.0732,\n",
       "                        0.2070,  0.1125, -0.1024,  0.0775,  0.0193, -0.1827, -0.0890, -0.0912,\n",
       "                        0.0963,  0.2196,  0.1764,  0.1979,  0.1371, -0.1155,  0.0979,  0.0183,\n",
       "                       -0.2265,  0.1394, -0.0674,  0.0758, -0.1087, -0.1746,  0.0377,  0.1903,\n",
       "                        0.0077, -0.0097, -0.0184,  0.0434, -0.0517, -0.1869, -0.2176, -0.2039,\n",
       "                       -0.1400, -0.0423, -0.1271, -0.0659,  0.1719,  0.1041,  0.2004, -0.1449,\n",
       "                       -0.0370,  0.0280, -0.1893, -0.2161,  0.2013,  0.1220, -0.0142,  0.1122,\n",
       "                        0.0852,  0.1362,  0.2056, -0.0363,  0.2209,  0.0949,  0.0798, -0.0553,\n",
       "                       -0.0722, -0.0206,  0.1668,  0.0253, -0.1514,  0.0801,  0.0625,  0.2211,\n",
       "                       -0.2261,  0.1992,  0.1776, -0.0754],\n",
       "                      [ 0.1578, -0.0887, -0.0004,  0.0132, -0.0432,  0.0304, -0.1923,  0.0097,\n",
       "                       -0.0167,  0.1473,  0.0547,  0.0547, -0.2234,  0.2167, -0.0144, -0.2253,\n",
       "                       -0.1982,  0.0201,  0.0543,  0.0376, -0.2221, -0.1174, -0.1070,  0.0319,\n",
       "                       -0.2069, -0.0265,  0.1293,  0.1555, -0.0230,  0.1776, -0.0558, -0.1257,\n",
       "                        0.0424, -0.0708, -0.2091, -0.1540, -0.0093,  0.1424,  0.1403, -0.0650,\n",
       "                        0.0245, -0.1230, -0.0498,  0.0532, -0.1393,  0.1431, -0.0203,  0.1289,\n",
       "                        0.1455,  0.0962,  0.1994, -0.0983, -0.0960, -0.2171,  0.2083, -0.0067,\n",
       "                       -0.2225,  0.2297,  0.1953,  0.1495, -0.0268,  0.1453, -0.0481, -0.1205,\n",
       "                        0.2331, -0.2179, -0.0209,  0.0106, -0.0948,  0.1656, -0.1535,  0.1501,\n",
       "                       -0.0497,  0.0599, -0.1325,  0.0805, -0.0462, -0.1526,  0.1749, -0.0979,\n",
       "                        0.2185,  0.1606, -0.0138, -0.1627, -0.0466, -0.0374,  0.1028, -0.0722,\n",
       "                       -0.1753, -0.0241, -0.2151, -0.0320, -0.1560, -0.1983,  0.0376, -0.0228,\n",
       "                       -0.0668,  0.2263,  0.1567,  0.1903],\n",
       "                      [ 0.1133,  0.0799,  0.1876,  0.0767, -0.0070, -0.1365,  0.1554, -0.0730,\n",
       "                        0.0660,  0.1029, -0.1290, -0.1533,  0.0645, -0.1318,  0.0114, -0.0907,\n",
       "                        0.0815,  0.1150,  0.1319, -0.2283, -0.1376,  0.0760,  0.2015, -0.0329,\n",
       "                       -0.2004,  0.1483, -0.0039, -0.1679, -0.0413, -0.0570, -0.2189,  0.1316,\n",
       "                        0.2291,  0.0939, -0.2287, -0.0481, -0.0227, -0.0624, -0.0862, -0.0236,\n",
       "                       -0.1790, -0.1022,  0.0942, -0.0826,  0.0842, -0.0435,  0.0004,  0.0286,\n",
       "                       -0.0267,  0.2312,  0.0525,  0.1886,  0.1466,  0.2131,  0.0627, -0.2272,\n",
       "                        0.1562,  0.0346,  0.2072,  0.0660, -0.0084,  0.1293,  0.1083,  0.0952,\n",
       "                        0.0071,  0.0331, -0.1968,  0.2001,  0.2104,  0.0250,  0.0488, -0.1291,\n",
       "                        0.0228,  0.1663, -0.0376,  0.1761,  0.1446, -0.1199,  0.2216,  0.1254,\n",
       "                        0.1630, -0.2062, -0.1872,  0.0747, -0.2167,  0.2191,  0.1821,  0.0757,\n",
       "                        0.0907, -0.1692, -0.0014,  0.1444,  0.0518,  0.2135, -0.1575, -0.1286,\n",
       "                        0.2077,  0.0081, -0.0125,  0.0734],\n",
       "                      [-0.1077, -0.1471, -0.0233,  0.1643,  0.0037, -0.2110, -0.1977, -0.1683,\n",
       "                        0.0342, -0.0761, -0.1786,  0.1532,  0.1036, -0.1583,  0.1097, -0.0459,\n",
       "                        0.1753, -0.1941, -0.1383,  0.0908,  0.0046, -0.0491, -0.0613,  0.1978,\n",
       "                        0.2274, -0.0474, -0.2016, -0.0217,  0.2074,  0.1093,  0.1898,  0.0774,\n",
       "                        0.1589, -0.2241, -0.0759, -0.0425,  0.1520,  0.0042,  0.1928,  0.0194,\n",
       "                       -0.1220,  0.1799, -0.1152,  0.1288,  0.1609, -0.0151,  0.1797, -0.2251,\n",
       "                       -0.0985,  0.0099,  0.1347, -0.1899, -0.0298, -0.2210, -0.0986, -0.0032,\n",
       "                        0.1060, -0.2208,  0.2192,  0.1759,  0.1489, -0.1167,  0.0773,  0.2244,\n",
       "                        0.0303,  0.2173,  0.1318, -0.1010,  0.0408, -0.1218,  0.1855,  0.0639,\n",
       "                       -0.0052, -0.1089,  0.0981, -0.1344, -0.2062, -0.1155,  0.0972, -0.1913,\n",
       "                        0.2241, -0.0338,  0.1004, -0.1881,  0.1861,  0.1289,  0.0455,  0.1943,\n",
       "                       -0.2199, -0.0558, -0.1610,  0.0252,  0.1751,  0.0112, -0.1998, -0.1544,\n",
       "                       -0.1987,  0.1357, -0.0400,  0.2017],\n",
       "                      [-0.0467, -0.1582, -0.2054,  0.1219, -0.0476,  0.1984, -0.2037, -0.1076,\n",
       "                        0.1707, -0.1400, -0.0715,  0.1011, -0.0849,  0.0542, -0.1663, -0.0742,\n",
       "                       -0.0038,  0.1461, -0.1370,  0.1808,  0.0811, -0.1183, -0.1548, -0.0692,\n",
       "                       -0.0335, -0.0746,  0.2328, -0.1927,  0.0167,  0.1096,  0.2000,  0.0489,\n",
       "                       -0.0378, -0.1140, -0.0296, -0.0904,  0.2221, -0.1174,  0.1435,  0.0164,\n",
       "                        0.0526,  0.0874,  0.0770, -0.1624,  0.0637,  0.0622,  0.1151, -0.0390,\n",
       "                        0.1366, -0.1230,  0.1780, -0.1820,  0.1456, -0.1855, -0.0685, -0.0471,\n",
       "                       -0.1406, -0.0471, -0.0911,  0.1202,  0.1590,  0.2202,  0.2204, -0.1663,\n",
       "                       -0.0245,  0.0412, -0.0964, -0.0971, -0.0582, -0.1100,  0.0025, -0.1937,\n",
       "                       -0.0187,  0.1106,  0.0068,  0.0113,  0.2011, -0.1475,  0.2132, -0.0075,\n",
       "                        0.0836,  0.1291,  0.0463,  0.2204,  0.0718,  0.2086, -0.0633,  0.1263,\n",
       "                        0.0715, -0.1353, -0.2195, -0.0038, -0.0307,  0.0583,  0.2093,  0.1854,\n",
       "                       -0.0910,  0.1660,  0.1424,  0.2013],\n",
       "                      [ 0.2253, -0.2105,  0.1189, -0.2127, -0.0843,  0.1678,  0.0487, -0.0829,\n",
       "                        0.0500, -0.0514, -0.1072, -0.0625,  0.1481,  0.0416,  0.0842,  0.1848,\n",
       "                        0.1694,  0.0992,  0.0867, -0.0258, -0.1626,  0.0062,  0.1920,  0.1463,\n",
       "                        0.0236, -0.0229, -0.1403, -0.1930, -0.0927, -0.0075, -0.0357,  0.2234,\n",
       "                        0.0982, -0.1074,  0.1002, -0.0281,  0.1823, -0.0952, -0.1752,  0.0261,\n",
       "                        0.0791, -0.1977,  0.1495,  0.0934, -0.2160, -0.1684,  0.1223, -0.0852,\n",
       "                        0.1184, -0.1880,  0.0037,  0.2171,  0.1890,  0.1869, -0.2211, -0.0346,\n",
       "                        0.1349, -0.1320, -0.2093,  0.1980,  0.1134,  0.1557, -0.1081,  0.0015,\n",
       "                       -0.2158, -0.1948,  0.0322,  0.1528,  0.0690, -0.1467, -0.1277,  0.1475,\n",
       "                        0.0538, -0.2118,  0.2087,  0.1231,  0.2064, -0.2080,  0.2228, -0.2044,\n",
       "                        0.1113, -0.1555, -0.2009,  0.0157,  0.0446, -0.2072, -0.1157,  0.0136,\n",
       "                       -0.0859,  0.0083,  0.0787, -0.2208, -0.2186,  0.2186, -0.0850,  0.0914,\n",
       "                       -0.0736, -0.1586, -0.0235,  0.2176],\n",
       "                      [-0.2001,  0.0270, -0.2284,  0.0560, -0.0387,  0.2260,  0.1860, -0.0881,\n",
       "                        0.1286, -0.1202,  0.1268,  0.2168,  0.1461, -0.1885,  0.0888,  0.1068,\n",
       "                       -0.0908, -0.1117,  0.0542,  0.1069, -0.0503, -0.0447, -0.1806,  0.0342,\n",
       "                        0.2011,  0.2234,  0.0754,  0.1659,  0.0992,  0.1612, -0.2247, -0.0180,\n",
       "                        0.0975,  0.1092,  0.0799, -0.1247,  0.2195, -0.0706, -0.1379, -0.2323,\n",
       "                        0.1364,  0.0954, -0.0846, -0.2316,  0.2248, -0.0292,  0.0376,  0.0668,\n",
       "                        0.0347, -0.0263, -0.1968,  0.0597, -0.1102,  0.1467, -0.1112,  0.2162,\n",
       "                       -0.1931,  0.0601, -0.0163,  0.0884, -0.0172,  0.0391, -0.0198, -0.0826,\n",
       "                       -0.1705,  0.2252, -0.1595,  0.0661, -0.1830,  0.1776,  0.0675,  0.0155,\n",
       "                        0.0403, -0.1167, -0.1981, -0.0980,  0.0074, -0.1531, -0.2027,  0.0787,\n",
       "                        0.2071, -0.0993, -0.0565,  0.2085, -0.1606,  0.1637, -0.1761, -0.1871,\n",
       "                        0.0859,  0.0808,  0.0891, -0.1563,  0.2283, -0.1837, -0.0920,  0.0621,\n",
       "                       -0.1876,  0.0584,  0.0340,  0.2158],\n",
       "                      [-0.1598,  0.1799, -0.1208,  0.1468,  0.1192,  0.2305,  0.0653,  0.1107,\n",
       "                        0.1261, -0.0021, -0.0566,  0.1269, -0.0166, -0.0612, -0.0870,  0.1134,\n",
       "                       -0.1650, -0.1990, -0.2161,  0.0587,  0.0090,  0.1028, -0.0648,  0.1214,\n",
       "                        0.1539,  0.1742,  0.1246, -0.0965,  0.2265,  0.1019, -0.0056,  0.1138,\n",
       "                        0.2129, -0.0618,  0.0636,  0.1191, -0.0929,  0.1219, -0.2134,  0.2004,\n",
       "                       -0.0507,  0.1814, -0.0007,  0.0133, -0.0918, -0.0177, -0.2195,  0.2031,\n",
       "                       -0.1291, -0.1636, -0.0133,  0.1069,  0.0935,  0.0604, -0.1670,  0.2297,\n",
       "                       -0.1049, -0.2161,  0.0198,  0.0459,  0.1622,  0.1036,  0.1680, -0.2291,\n",
       "                        0.0023,  0.1903, -0.0734, -0.0350, -0.0087, -0.1809,  0.0522, -0.0284,\n",
       "                        0.0523, -0.0997,  0.2159,  0.2135, -0.1338, -0.0071,  0.0746,  0.0190,\n",
       "                        0.1827, -0.0120,  0.0534,  0.0714,  0.0850, -0.0297, -0.0641,  0.1471,\n",
       "                       -0.2040, -0.1615,  0.1322,  0.2007, -0.0838,  0.1961, -0.0825,  0.1473,\n",
       "                       -0.0179, -0.2194, -0.1865, -0.1934],\n",
       "                      [-0.0652, -0.1786,  0.0463,  0.2312,  0.0013,  0.0254, -0.2058,  0.0332,\n",
       "                        0.0103,  0.1494, -0.1639, -0.0040, -0.0014,  0.0314, -0.0850,  0.1279,\n",
       "                        0.2314, -0.2288, -0.1966, -0.2172,  0.0333,  0.2309,  0.0646,  0.1552,\n",
       "                       -0.0528, -0.0614, -0.1307, -0.1067, -0.1489,  0.0105,  0.1076, -0.0061,\n",
       "                       -0.1709,  0.0153, -0.1435, -0.2243, -0.1611, -0.1442,  0.0610,  0.0492,\n",
       "                        0.1331,  0.0244,  0.2250,  0.0130, -0.1940,  0.0655, -0.0208, -0.0059,\n",
       "                        0.1342,  0.0308, -0.1753,  0.0582, -0.0663,  0.1661, -0.0255, -0.1468,\n",
       "                       -0.0342, -0.1006,  0.0069, -0.1765,  0.1789,  0.0668, -0.1936, -0.0842,\n",
       "                       -0.0894, -0.0150,  0.1249, -0.1097, -0.1060,  0.2087,  0.1334, -0.1425,\n",
       "                        0.1485, -0.2243, -0.0896,  0.0797,  0.0200, -0.0193, -0.2274, -0.1125,\n",
       "                       -0.0368, -0.1726,  0.0051,  0.1718, -0.1767,  0.0275,  0.1602,  0.0296,\n",
       "                        0.0360,  0.1623,  0.0740,  0.2248, -0.0374,  0.0513,  0.1843,  0.1375,\n",
       "                       -0.0208,  0.0416,  0.1830, -0.1766]])),\n",
       "             ('linear_selu_stack.Output Layer.bias',\n",
       "              tensor([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]))])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.state_dict()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:40.019027Z",
     "start_time": "2025-06-26T01:43:33.217395Z"
    }
   },
   "outputs": [],
   "source": [
    "from torch.utils.tensorboard import SummaryWriter\n",
    "class TensorboardLogger:\n",
    "    \"\"\"\n",
    "    Tensorboard日志记录类：记录训练过程中的损失和准确率\n",
    "    \n",
    "    参数:\n",
    "        log_dir: 日志保存目录,log_dir的父目录不要有中文\n",
    "    \"\"\"\n",
    "    def __init__(self, log_dir='tensorboard_logs'):\n",
    "\n",
    "        import os\n",
    "        \n",
    "        # 确保日志目录存在\n",
    "        if not os.path.exists(log_dir):\n",
    "            os.makedirs(log_dir)\n",
    "            \n",
    "        self.writer = SummaryWriter(log_dir) # 实例化SummaryWriter, log_dir是log存放路径，flush_secs是每隔多少秒写入磁盘\n",
    "        \n",
    "    def log_training(self, epoch, train_loss, train_acc):\n",
    "        \"\"\"\n",
    "        记录训练数据\n",
    "        \n",
    "        参数:\n",
    "            epoch: 当前训练轮数\n",
    "            train_loss: 训练损失\n",
    "            train_acc: 训练准确率\n",
    "        \"\"\"\n",
    "        self.writer.add_scalar('训练/损失', train_loss, epoch)\n",
    "        self.writer.add_scalar('训练/准确率', train_acc, epoch)\n",
    "        \n",
    "    def log_validation(self, epoch, val_loss, val_acc):\n",
    "        \"\"\"\n",
    "        记录验证数据\n",
    "        \n",
    "        参数:\n",
    "            epoch: 当前训练轮数\n",
    "            val_loss: 验证损失\n",
    "            val_acc: 验证准确率\n",
    "        \"\"\"\n",
    "        self.writer.add_scalar('验证/损失', val_loss, epoch)\n",
    "        self.writer.add_scalar('验证/准确率', val_acc, epoch)\n",
    "    \n",
    "    def log_lr(self, epoch, lr):\n",
    "        \"\"\"\n",
    "        记录学习率\n",
    "        \n",
    "        参数:\n",
    "            epoch: 当前训练轮数\n",
    "            lr: 学习率\n",
    "        \"\"\"\n",
    "        self.writer.add_scalar('学习率', lr, epoch)\n",
    "        \n",
    "    def log_model_graph(self, model, images):\n",
    "        \"\"\"\n",
    "        记录模型结构图\n",
    "        \n",
    "        参数:\n",
    "            model: 模型\n",
    "            images: 输入图像样本\n",
    "        \"\"\"\n",
    "        self.writer.add_graph(model, images)\n",
    "        \n",
    "    def close(self):\n",
    "        \"\"\"\n",
    "        关闭Tensorboard写入器\n",
    "        \"\"\"\n",
    "        self.writer.close()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 设置交叉熵损失函数，SGD优化器"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:40.023837Z",
     "start_time": "2025-06-26T01:43:40.019952Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "损失函数: CrossEntropyLoss()\n",
      "优化器: SGD (\n",
      "Parameter Group 0\n",
      "    dampening: 0\n",
      "    differentiable: False\n",
      "    foreach: None\n",
      "    fused: None\n",
      "    lr: 0.01\n",
      "    maximize: False\n",
      "    momentum: 0.9\n",
      "    nesterov: False\n",
      "    weight_decay: 0\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "model = NeuralNetwork()\n",
    "# 定义损失函数和优化器\n",
    "loss_fn = nn.CrossEntropyLoss()  # 交叉熵损失函数，适用于多分类问题，里边会做softmax，还有会把0-9标签转换成one-hot编码\n",
    "# 用少量样本就能更新权重，训练更快，且更容易跳出局部最优\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)  # SGD优化器，学习率为0.01，动量为0.9\n",
    "\n",
    "print(\"损失函数:\", loss_fn)\n",
    "print(\"优化器:\", optimizer)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:43:40.035848Z",
     "start_time": "2025-06-26T01:43:40.032419Z"
    }
   },
   "outputs": [],
   "source": [
    "model = NeuralNetwork(layers_num=19)\n",
    "\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)  # SGD优化器，学习率为0.01，动量为0.9"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:45:37.732814Z",
     "start_time": "2025-06-26T01:43:40.035848Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "使用设备: cuda:0\n",
      "训练开始，共43000步\n"
     ]
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "a689cfa93d484c48a4a63f8887f7a857",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "  0%|          | 0/43000 [00:00<?, ?it/s]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "早停触发! 最佳验证准确率: 86.9200\n",
      "早停: 在14500 步\n"
     ]
    }
   ],
   "source": [
    "device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n",
    "print(f\"使用设备: {device}\")\n",
    "model = model.to(device) #将模型移动到GPU\n",
    "early_stopping=EarlyStopping(patience=5, delta=0.001)\n",
    "model_saver=ModelSaver(save_dir='model_weights', save_best_only=True)\n",
    "#tensorboard_logger=TensorboardLogger(log_dir='logs')\n",
    "\n",
    "model, history = train_classification_model(model, train_loader, val_loader, loss_fn, optimizer, device, num_epochs=50, early_stopping=early_stopping, model_saver=model_saver, tensorboard_logger=None)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:45:37.737721Z",
     "start_time": "2025-06-26T01:45:37.732814Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'loss': 0.3078381419181824, 'acc': 87.5, 'step': 14401},\n",
       " {'loss': 0.3762255907058716, 'acc': 81.25, 'step': 14402},\n",
       " {'loss': 0.17525307834148407, 'acc': 90.625, 'step': 14403},\n",
       " {'loss': 0.20517101883888245, 'acc': 90.625, 'step': 14404},\n",
       " {'loss': 0.31943944096565247, 'acc': 87.5, 'step': 14405},\n",
       " {'loss': 0.18556581437587738, 'acc': 90.625, 'step': 14406},\n",
       " {'loss': 0.4281684458255768, 'acc': 85.9375, 'step': 14407},\n",
       " {'loss': 0.3264564275741577, 'acc': 89.0625, 'step': 14408},\n",
       " {'loss': 0.17760300636291504, 'acc': 95.3125, 'step': 14409},\n",
       " {'loss': 0.30837807059288025, 'acc': 90.625, 'step': 14410},\n",
       " {'loss': 0.33863595128059387, 'acc': 87.5, 'step': 14411},\n",
       " {'loss': 0.3151654601097107, 'acc': 89.0625, 'step': 14412},\n",
       " {'loss': 0.3629929721355438, 'acc': 92.1875, 'step': 14413},\n",
       " {'loss': 0.4516843259334564, 'acc': 82.8125, 'step': 14414},\n",
       " {'loss': 0.40490832924842834, 'acc': 85.9375, 'step': 14415},\n",
       " {'loss': 0.4990604519844055, 'acc': 82.8125, 'step': 14416},\n",
       " {'loss': 0.24204760789871216, 'acc': 92.1875, 'step': 14417},\n",
       " {'loss': 0.5507980585098267, 'acc': 76.5625, 'step': 14418},\n",
       " {'loss': 0.41288816928863525, 'acc': 79.6875, 'step': 14419},\n",
       " {'loss': 0.5022766590118408, 'acc': 82.8125, 'step': 14420},\n",
       " {'loss': 0.2592637836933136, 'acc': 90.625, 'step': 14421},\n",
       " {'loss': 0.29209524393081665, 'acc': 89.0625, 'step': 14422},\n",
       " {'loss': 0.25673314929008484, 'acc': 92.1875, 'step': 14423},\n",
       " {'loss': 0.46279826760292053, 'acc': 82.8125, 'step': 14424},\n",
       " {'loss': 0.3614244759082794, 'acc': 87.5, 'step': 14425},\n",
       " {'loss': 0.5126544237136841, 'acc': 84.375, 'step': 14426},\n",
       " {'loss': 0.2471858561038971, 'acc': 92.1875, 'step': 14427},\n",
       " {'loss': 0.2784994840621948, 'acc': 92.1875, 'step': 14428},\n",
       " {'loss': 0.3703894019126892, 'acc': 87.5, 'step': 14429},\n",
       " {'loss': 0.24499544501304626, 'acc': 95.3125, 'step': 14430},\n",
       " {'loss': 0.32283324003219604, 'acc': 87.5, 'step': 14431},\n",
       " {'loss': 0.31911584734916687, 'acc': 87.5, 'step': 14432},\n",
       " {'loss': 0.24289292097091675, 'acc': 92.1875, 'step': 14433},\n",
       " {'loss': 0.43194830417633057, 'acc': 92.1875, 'step': 14434},\n",
       " {'loss': 0.38751596212387085, 'acc': 87.5, 'step': 14435},\n",
       " {'loss': 0.29418057203292847, 'acc': 92.1875, 'step': 14436},\n",
       " {'loss': 0.41341400146484375, 'acc': 81.25, 'step': 14437},\n",
       " {'loss': 0.44293174147605896, 'acc': 85.9375, 'step': 14438},\n",
       " {'loss': 0.3879810869693756, 'acc': 85.9375, 'step': 14439},\n",
       " {'loss': 0.32096680998802185, 'acc': 87.5, 'step': 14440},\n",
       " {'loss': 0.6683925986289978, 'acc': 78.125, 'step': 14441},\n",
       " {'loss': 0.2081986963748932, 'acc': 92.1875, 'step': 14442},\n",
       " {'loss': 0.42314696311950684, 'acc': 87.5, 'step': 14443},\n",
       " {'loss': 0.4043982923030853, 'acc': 87.5, 'step': 14444},\n",
       " {'loss': 0.24270719289779663, 'acc': 92.1875, 'step': 14445},\n",
       " {'loss': 0.18806873261928558, 'acc': 98.4375, 'step': 14446},\n",
       " {'loss': 0.18062502145767212, 'acc': 93.75, 'step': 14447},\n",
       " {'loss': 0.42178401350975037, 'acc': 87.5, 'step': 14448},\n",
       " {'loss': 0.19753551483154297, 'acc': 93.75, 'step': 14449},\n",
       " {'loss': 0.18159465491771698, 'acc': 93.75, 'step': 14450},\n",
       " {'loss': 0.2763391137123108, 'acc': 90.625, 'step': 14451},\n",
       " {'loss': 0.25695446133613586, 'acc': 90.625, 'step': 14452},\n",
       " {'loss': 0.587938129901886, 'acc': 81.25, 'step': 14453},\n",
       " {'loss': 0.23317189514636993, 'acc': 93.75, 'step': 14454},\n",
       " {'loss': 0.5816512703895569, 'acc': 78.125, 'step': 14455},\n",
       " {'loss': 0.3113836348056793, 'acc': 87.5, 'step': 14456},\n",
       " {'loss': 0.48377957940101624, 'acc': 87.5, 'step': 14457},\n",
       " {'loss': 0.2896975874900818, 'acc': 87.5, 'step': 14458},\n",
       " {'loss': 0.357698917388916, 'acc': 85.9375, 'step': 14459},\n",
       " {'loss': 0.42706063389778137, 'acc': 84.375, 'step': 14460},\n",
       " {'loss': 0.5295966863632202, 'acc': 82.8125, 'step': 14461},\n",
       " {'loss': 0.32900914549827576, 'acc': 89.0625, 'step': 14462},\n",
       " {'loss': 0.2424028515815735, 'acc': 90.625, 'step': 14463},\n",
       " {'loss': 0.2090238481760025, 'acc': 92.1875, 'step': 14464},\n",
       " {'loss': 0.37779727578163147, 'acc': 89.0625, 'step': 14465},\n",
       " {'loss': 0.5637707114219666, 'acc': 78.125, 'step': 14466},\n",
       " {'loss': 0.2967788577079773, 'acc': 93.75, 'step': 14467},\n",
       " {'loss': 0.33083680272102356, 'acc': 84.375, 'step': 14468},\n",
       " {'loss': 0.20547565817832947, 'acc': 93.75, 'step': 14469},\n",
       " {'loss': 0.2782742381095886, 'acc': 92.1875, 'step': 14470},\n",
       " {'loss': 0.45482954382896423, 'acc': 85.9375, 'step': 14471},\n",
       " {'loss': 0.48693138360977173, 'acc': 81.25, 'step': 14472},\n",
       " {'loss': 0.27672484517097473, 'acc': 92.1875, 'step': 14473},\n",
       " {'loss': 0.30121293663978577, 'acc': 84.375, 'step': 14474},\n",
       " {'loss': 0.39979735016822815, 'acc': 78.125, 'step': 14475},\n",
       " {'loss': 0.3452923595905304, 'acc': 89.0625, 'step': 14476},\n",
       " {'loss': 0.5271669030189514, 'acc': 79.6875, 'step': 14477},\n",
       " {'loss': 0.32632192969322205, 'acc': 89.0625, 'step': 14478},\n",
       " {'loss': 0.35653653740882874, 'acc': 87.5, 'step': 14479},\n",
       " {'loss': 0.23484674096107483, 'acc': 92.1875, 'step': 14480},\n",
       " {'loss': 0.5943416953086853, 'acc': 81.25, 'step': 14481},\n",
       " {'loss': 0.34598681330680847, 'acc': 89.0625, 'step': 14482},\n",
       " {'loss': 0.37325519323349, 'acc': 84.375, 'step': 14483},\n",
       " {'loss': 0.5097419023513794, 'acc': 84.375, 'step': 14484},\n",
       " {'loss': 0.3046087324619293, 'acc': 87.5, 'step': 14485},\n",
       " {'loss': 0.39241185784339905, 'acc': 84.375, 'step': 14486},\n",
       " {'loss': 0.24597002565860748, 'acc': 90.625, 'step': 14487},\n",
       " {'loss': 0.300658255815506, 'acc': 90.625, 'step': 14488},\n",
       " {'loss': 0.33744654059410095, 'acc': 89.0625, 'step': 14489},\n",
       " {'loss': 0.5211435556411743, 'acc': 76.5625, 'step': 14490},\n",
       " {'loss': 0.2738265097141266, 'acc': 87.5, 'step': 14491},\n",
       " {'loss': 0.17539604008197784, 'acc': 95.3125, 'step': 14492},\n",
       " {'loss': 0.4764571487903595, 'acc': 85.9375, 'step': 14493},\n",
       " {'loss': 0.2931664288043976, 'acc': 84.375, 'step': 14494},\n",
       " {'loss': 0.5179536938667297, 'acc': 81.25, 'step': 14495},\n",
       " {'loss': 0.4755094051361084, 'acc': 82.8125, 'step': 14496},\n",
       " {'loss': 0.27730515599250793, 'acc': 90.625, 'step': 14497},\n",
       " {'loss': 0.4043479263782501, 'acc': 81.25, 'step': 14498},\n",
       " {'loss': 0.4294818639755249, 'acc': 81.25, 'step': 14499}]"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "history['train'][-100:-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:45:37.741226Z",
     "start_time": "2025-06-26T01:45:37.737721Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'loss': 2.57584310836792, 'acc': 15.94, 'step': 0},\n",
       " {'loss': 0.5931374574661255, 'acc': 79.04, 'step': 500},\n",
       " {'loss': 0.5498601650953293, 'acc': 81.18, 'step': 1000},\n",
       " {'loss': 0.5230918625354767, 'acc': 82.3, 'step': 1500},\n",
       " {'loss': 0.5426174892663955, 'acc': 81.9, 'step': 2000},\n",
       " {'loss': 0.5051771918058395, 'acc': 82.92, 'step': 2500},\n",
       " {'loss': 0.4747399622678757, 'acc': 83.4, 'step': 3000},\n",
       " {'loss': 0.4859612888097763, 'acc': 83.02, 'step': 3500},\n",
       " {'loss': 0.47189094165563583, 'acc': 84.26, 'step': 4000},\n",
       " {'loss': 0.4535395675778389, 'acc': 84.74, 'step': 4500},\n",
       " {'loss': 0.49197857365608216, 'acc': 83.56, 'step': 5000},\n",
       " {'loss': 0.4662253160715103, 'acc': 84.86, 'step': 5500},\n",
       " {'loss': 0.4441366427183151, 'acc': 85.32, 'step': 6000},\n",
       " {'loss': 0.4298621846437454, 'acc': 85.12, 'step': 6500},\n",
       " {'loss': 0.4356474034667015, 'acc': 85.24, 'step': 7000},\n",
       " {'loss': 0.442287854552269, 'acc': 85.64, 'step': 7500},\n",
       " {'loss': 0.42782788096666335, 'acc': 86.02, 'step': 8000},\n",
       " {'loss': 0.4341088644504547, 'acc': 85.52, 'step': 8500},\n",
       " {'loss': 0.4234548621892929, 'acc': 85.64, 'step': 9000},\n",
       " {'loss': 0.4269675022006035, 'acc': 86.1, 'step': 9500},\n",
       " {'loss': 0.40585755459070205, 'acc': 85.8, 'step': 10000},\n",
       " {'loss': 0.39757434158325194, 'acc': 86.18, 'step': 10500},\n",
       " {'loss': 0.41921619262695314, 'acc': 85.62, 'step': 11000},\n",
       " {'loss': 0.38664326326847076, 'acc': 86.86, 'step': 11500},\n",
       " {'loss': 0.3920369879722595, 'acc': 86.92, 'step': 12000},\n",
       " {'loss': 0.3939390296459198, 'acc': 86.76, 'step': 12500},\n",
       " {'loss': 0.40504531331062316, 'acc': 86.26, 'step': 13000},\n",
       " {'loss': 0.4050988998174667, 'acc': 86.62, 'step': 13500},\n",
       " {'loss': 0.3966196913599968, 'acc': 86.82, 'step': 14000}]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "history['val'][-1000:-1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 绘制损失曲线和准确率曲线"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:45:37.744941Z",
     "start_time": "2025-06-26T01:45:37.741226Z"
    }
   },
   "outputs": [],
   "source": [
    "# 导入绘图库\n",
    "import matplotlib.pyplot as plt\n",
    "from matplotlib import font_manager\n",
    "def plot_learning_curves1(history):\n",
    "    # 设置中文字体支持\n",
    "    plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体\n",
    "    plt.rcParams['axes.unicode_minus'] = False    # 解决负号显示问题\n",
    "\n",
    "    # 创建一个图形，包含两个子图（损失和准确率）\n",
    "    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 5))\n",
    "\n",
    "    # 绘制损失曲线\n",
    "    epochs = range(1, len(history['train_loss']) + 1)\n",
    "    ax1.plot(epochs, history['train_loss'], 'b-', label='训练损失')\n",
    "    ax1.plot(epochs, history['val_loss'], 'r-', label='验证损失')\n",
    "    ax1.set_title('训练与验证损失')\n",
    "    ax1.set_xlabel('轮次')\n",
    "    ax1.set_ylabel('损失')\n",
    "    ax1.legend()\n",
    "    ax1.grid(True)\n",
    "\n",
    "    # 绘制准确率曲线\n",
    "    ax2.plot(epochs, history['train_acc'], 'b-', label='训练准确率')\n",
    "    ax2.plot(epochs, history['val_acc'], 'r-', label='验证准确率')\n",
    "    ax2.set_title('训练与验证准确率')\n",
    "    ax2.set_xlabel('轮次')\n",
    "    ax2.set_ylabel('准确率 (%)')\n",
    "    ax2.legend()\n",
    "    ax2.grid(True)\n",
    "\n",
    "    plt.tight_layout()\n",
    "    plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:45:37.816716Z",
     "start_time": "2025-06-26T01:45:37.744941Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_learning_curves(history, sample_step=500)  #横坐标是 steps"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:45:37.818553Z",
     "start_time": "2025-06-26T01:45:37.816716Z"
    }
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-06-26T01:48:40.300725Z",
     "start_time": "2025-06-26T01:48:39.548524Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(86.26, 0.3938860222578049)"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 在测试集上评估模型\n",
    "test_accuracy = evaluate_model(model, test_loader, device, loss_fn)\n",
    "test_accuracy\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
